/*
 * File      : spi_wifi_rw009.h
 * This file is part of RT-Thread RTOS
 * Copyright by Shanghai Real-Thread Electronic Technology Co.,Ltd
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2014-07-31     aozima       the first version
 * 2014-09-18     aozima       update command & response.
 */

#ifndef SPI_WIFI_H_INCLUDED
#define SPI_WIFI_H_INCLUDED

#include <stdint.h>

// little-endian
struct spi_cmd_request {
	uint32_t flag;
	uint32_t M2S_len; // master to slave data len.
	uint32_t magic1;
	uint32_t magic2;
};

#define CMD_MAGIC1          (0x67452301)
#define CMD_MAGIC2          (0xEFCDAB89)

#define CMD_FLAG_MRDY       (0x01)

// little-endian
struct spi_response {
	uint32_t flag;
	uint32_t S2M_len; // slave to master data len.
	uint32_t magic1;
	uint32_t magic2;
};

#define RESP_FLAG_SRDY      (0x01)
#define RESP_MAGIC1         (0x98BADCFE)
#define RESP_MAGIC2         (0x10325476)

/* spi slave configure. */
#define SPI_MAX_DATA_LEN    1520
#define SPI_TX_POOL_SIZE    2
#define SPI_RX_POOL_SIZE    2

typedef enum {
	data_type_eth_data = 0,
	data_type_cmd,
	data_type_resp,
	data_type_status,
}
app_data_type_typedef;

struct spi_data_packet {
	uint32_t data_len;
	uint32_t data_type;
	char buffer[SPI_MAX_DATA_LEN];
};

/********************************* RW009 **************************************/

/* option */
#define RW009_CMD_TIMEOUT           (RT_TICK_PER_SECOND*3)
#define SSID_NAME_LENGTH_MAX        (32)
#define PASSWORD_LENGTH_MAX         (64)

typedef enum {
	MODE_STATION = 0,
	MODE_SOFTAP = 1,
} wifi_mode_t;

typedef struct _rw009_ap_info {
	char        ssid[SSID_NAME_LENGTH_MAX];
	uint8_t     bssid[8]; // 6byte + 2byte PAD.
	int         rssi;               /* Receive Signal Strength Indication in dBm. */
	uint32_t    max_data_rate;      /* Maximum data rate in kilobits/s */
	uint32_t    security;           /* Security type  */
	uint32_t    channel;            /* Radio channel that the AP beacon was received on   */
} rw009_ap_info;

typedef struct _rw009_cmd_init {
	uint32_t mode;
} rw009_cmd_init;

typedef struct _rw009_resp_init {
	uint8_t mac[8];     // 6byte + 2byte PAD.
	uint8_t sn[24];     // serial.
	char version[16];   // firmware version.
} rw009_resp_init;

typedef struct _rw009_cmd_easy_join {
	char ssid[SSID_NAME_LENGTH_MAX];
	char passwd[PASSWORD_LENGTH_MAX];
} rw009_cmd_easy_join;

typedef struct _rw009_cmd_join {
	uint8_t bssid[8]; // 6byte + 2byte PAD.
	char passwd[PASSWORD_LENGTH_MAX];
} rw009_cmd_join;

typedef struct _rw009_cmd_rssi {
	uint8_t bssid[8]; // 6byte + 2byte PAD.
} rw009_cmd_rssi;

typedef struct _rw009_cmd_softap {
	char ssid[SSID_NAME_LENGTH_MAX];
	char passwd[PASSWORD_LENGTH_MAX];

	uint32_t    security;           /* Security type. */
	uint32_t    channel;            /* Radio channel that the AP beacon was received on   */
} rw009_cmd_softap;

typedef struct _rw009_resp_join {
	rw009_ap_info ap_info;
} rw009_resp_join;

struct rw009_cmd {
	uint32_t cmd;
	uint32_t len;

	/** command body */
	union {
		rw009_cmd_init init;
		rw009_cmd_easy_join easy_join;
		rw009_cmd_join join;
		rw009_cmd_rssi rssi;
		rw009_cmd_softap softap;
	} params;
};

struct rw009_resp {
	uint32_t cmd;
	uint32_t len;

	int32_t result; // result for CMD.

	/** resp Body */
	union {
		rw009_resp_init init;
		rw009_ap_info ap_info;
	} resp;
};

#define RW009_CMD_INIT              128
#define RW009_CMD_SCAN              129
#define RW009_CMD_JOIN              130
#define RW009_CMD_EASY_JOIN         131
#define RW009_CMD_RSSI              132
#define RW009_CMD_SOFTAP            133

/** cond !ADDTHIS*/
#define SHARED_ENABLED  0x00008000
#define WPA_SECURITY    0x00200000
#define WPA2_SECURITY   0x00400000
#define WPS_ENABLED     0x10000000
#define WEP_ENABLED        0x0001
#define TKIP_ENABLED        0x0002
#define AES_ENABLED        0x0004
#define WSEC_SWFLAG        0x0008
/** endcond */
/**
 * Enumeration of Wi-Fi security modes
 */
typedef enum {
	SECURITY_OPEN           = 0,                                                /**< Open security                           */
	SECURITY_WEP_PSK        = WEP_ENABLED,                                      /**< WEP Security with open authentication   */
	SECURITY_WEP_SHARED     = (WEP_ENABLED | SHARED_ENABLED),                   /**< WEP Security with shared authentication */
	SECURITY_WPA_TKIP_PSK   = (WPA_SECURITY  | TKIP_ENABLED),                   /**< WPA Security with TKIP                  */
	SECURITY_WPA_AES_PSK    = (WPA_SECURITY  | AES_ENABLED),                    /**< WPA Security with AES                   */
	SECURITY_WPA2_AES_PSK   = (WPA2_SECURITY | AES_ENABLED),                    /**< WPA2 Security with AES                  */
	SECURITY_WPA2_TKIP_PSK  = (WPA2_SECURITY | TKIP_ENABLED),                   /**< WPA2 Security with TKIP                 */
	SECURITY_WPA2_MIXED_PSK = (WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED),     /**< WPA2 Security with AES & TKIP           */

	SECURITY_WPS_OPEN       = WPS_ENABLED,                                      /**< WPS with open security                  */
	SECURITY_WPS_SECURE     = (WPS_ENABLED | AES_ENABLED),                      /**< WPS with AES security                   */

	SECURITY_UNKNOWN        = -1,                                               /**< May be returned by scan function if security is unknown. Do not pass this to the join function! */

	SECURITY_FORCE_32_BIT   = 0x7fffffff                                        /**< Exists only to force wiced_security_t type to 32 bits */
} security_t;

/* porting */
extern void spi_wifi_hw_init(void);
extern void spi_wifi_int_cmd(rt_bool_t cmd);
extern rt_bool_t spi_wifi_is_busy(void);

/* export API. */
extern rt_err_t rt_hw_wifi_init(const char* spi_device_name, wifi_mode_t mode);
extern int32_t rw009_rssi(void);
extern rt_err_t rw009_join(const char* SSID, const char* passwd);
extern rt_err_t rw009_softap(const char* SSID, const char* passwd, uint32_t security, uint32_t channel);

#endif // SPI_WIFI_H_INCLUDED
